/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "hoods_ability_slice.h"

#include <sys/types.h>

#include "ability_env.h"
#include "ability_manager.h"
#include "ability_slice.h"
#include "securec.h"
#include "file.h"

#include "week_date.h"
#include "ui_config.h"
#include "define.h"

#include "file_server.h"

using namespace std;

namespace OHOS {
REGISTER_AS(HoodsAbilitySlice)

static void GroupViewClear(const UIView *view)
{
    if (view == nullptr || view->IsViewGroup() == false) {
        return;
    }

    UIView *child = static_cast<const UIViewGroup*>(view)->GetChildrenHead();
    UIView *childNext = nullptr;

    while (child != nullptr) {
        childNext = child->GetNextSibling();
        if (child->IsViewGroup()) {
            GroupViewClear(child);
        }
        delete child;
        child = childNext;
    }
}

HoodsAbilitySlice::HoodsAbilitySlice()
{
    for (int i = 0; i < LABEL_COUNT; i++) {
        listLabel_[i] = nullptr;
    }
    printf("[%s|%d]\n", __func__, __LINE__);
    Task::Init();
    SetPeriod(TASK_TIME_PERIOD);
}

HoodsAbilitySlice::~HoodsAbilitySlice()
{
    if (background_ != nullptr) {
        delete background_;
        background_ = nullptr;
    }

    if (backButton_ != nullptr) {
        delete backButton_;
        backButton_ = nullptr;
    }

    if (backClickImage_ != nullptr) {
        delete backClickImage_;
        backClickImage_ = nullptr;
    }

    if (weatherDateGroup_ != nullptr) {
        delete weatherDateGroup_;
        weatherDateGroup_ = nullptr;
    }

    if (weatherBackground_ != nullptr) {
        delete weatherBackground_;
        weatherBackground_ = nullptr;
    }

    if (dateLabel_ != nullptr) {
        delete dateLabel_;
        dateLabel_ = nullptr;
    }

    if (timeLabel_ != nullptr) {
        delete timeLabel_;
        timeLabel_ = nullptr;
    }

    if (weekLabel_ != nullptr) {
        delete weekLabel_;
        weekLabel_ = nullptr;
    }

    if (tempLabel_ != nullptr) {
        delete tempLabel_;
        tempLabel_ = nullptr;
    }

    if (weatherLabel_ != nullptr) {
        delete weatherLabel_;
        weatherLabel_ = nullptr;
    }

    if (itemGroup_ != nullptr) {
        GroupViewClear(itemGroup_);
        delete itemGroup_;
        itemGroup_ = nullptr;
    }

    if (backClickListener_ != nullptr) {
        delete backClickListener_;
        backClickListener_ = nullptr;
    }

    if (dialog_ != nullptr) {
        delete dialog_;
        dialog_ = nullptr;
    }

    for (int i = 0; i < LABEL_COUNT; i++) {
        if (listLabel_[i] != nullptr) {
            delete listLabel_[i];
            listLabel_[i] = nullptr;
        }
    }
}

void HoodsAbilitySlice::UpdateTime(bool draw)
{
    char hour_min[TMP_BUF_SIZE] = {0};
    char month_day[TMP_BUF_SIZE] = {0};
    char *week_day;

    const int16_t january = 1;
    const int16_t commonYear = 1900;

    time_t t = time(nullptr);
    struct tm *st = localtime(&t);
    if (st->tm_min == g_minute_) {
        return;
    }

    g_minute_ = st->tm_min;
    week_day = (char *)WeekDate::GetWeekByYear(st->tm_year + commonYear, st->tm_mon + january, st->tm_mday, WeekDate::LANGUAGE_ENG);
    (void)sprintf_s(hour_min, sizeof(hour_min), "%02d:%02d", st->tm_hour, st->tm_min);
    (void)sprintf_s(month_day, sizeof(month_day), "%02d月:%02d日", st->tm_mon + january, st->tm_mday);
    dateLabel_->SetText((char *)month_day);
    timeLabel_->SetText((char *)hour_min);
    weekLabel_->SetText(week_day);

    if (draw) {
        dateLabel_->Invalidate();
        timeLabel_->Invalidate();
        weekLabel_->Invalidate();
    }
}

void HoodsAbilitySlice::UpdateVideoImage(int type)
{
    char text[TMP_BUF_SIZE] = {0};
    int total = 0;
    char *msg[] = {(char *)"视频", (char *)"图片"};
    if (type == IMAGE_ITEM) {
        total = g_pictrueNumber_;
    } else if (type == VIDEO_ITEM) {
        total = g_videoNumber_;
    } else {
        return;
    }

    (void)sprintf_s(text, sizeof(text), "%s(%d)", msg[type], total);

    if (listLabel_[type] != nullptr) {
        listLabel_[type]->SetText((char *)text);
    }
}

static UILabel *CreateLabel(const char *text, UI_RECT rect, int fontsize)
{
    UILabel *label = new UILabel();
    label->SetPosition(rect.x, rect.y, rect.w, rect.h);
    label->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER, UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER);
    label->SetStyle(STYLE_BACKGROUND_OPA, 0);
    label->SetFont(FONT_NAME, fontsize);
    label->SetStyle(STYLE_TEXT_COLOR, Color::ColorTo32(Color::Black()));
    label->SetText(text);

    return label;
}

void HoodsAbilitySlice::SetTimeWeatherView()
{
    char *text[LABEL_COUNT] = {
        (char *)"2021年11月10日",
        (char *)"00:00",
        (char *)"SUN",
        (char *)"28 ℃",
        (char *)"多云"
    };
    UI_RECT labelRect[LABEL_COUNT] = {
        {WEA_DATE_X_DATE, WEA_DATE_Y_DATE, WEA_DATE_W_DATE, WEA_DATE_H_DATE},
        {WEA_DATE_X_TIME, WEA_DATE_Y_TIME, WEA_DATE_W_TIME, WEA_DATE_H_TIME},
        {WEA_DATE_X_WEEK, WEA_DATE_Y_WEEK, WEA_DATE_W_WEEK, WEA_DATE_H_WEEK},
        {WEA_DATE_X_TEMP, WEA_DATE_Y_TEMP, WEA_DATE_W_TEMP, WEA_DATE_H_TEMP},
        {WEA_DATE_X_WEA,  WEA_DATE_Y_WEA,  WEA_DATE_W_WEA,  WEA_DATE_H_WEA }
    };
    int fonstSize[LABEL_COUNT] = {FONT_SIZE_20, FONT_SIZE_64, FONT_SIZE_24, FONT_SIZE_24, FONT_SIZE_24};
    UILabel *gLabel[LABEL_COUNT];
    printf("[%s|%d]\n", __func__, __LINE__);
    weatherDateGroup_ = new UIViewGroup();
    weatherDateGroup_->SetPosition(WEA_DATE_X_POS, WEA_DATE_Y_POS, WEA_DATE_WIDTH, WEA_DATE_HEIGHT);
    weatherDateGroup_->SetStyle(STYLE_BACKGROUND_OPA, 0);

    char iconPath[256] = {0};
    const char *pathHead = GetSrcPath();
    (void)sprintf_s(iconPath, sizeof(iconPath), "%s/%s", pathHead, BIG_ITEM_BKG);

    weatherBackground_ = new UIImageView();
    weatherBackground_->SetPosition(0, 0, WEA_DATE_WIDTH, WEA_DATE_HEIGHT);
    weatherBackground_->SetSrc((char *)iconPath);
    weatherBackground_->SetStyle(STYLE_BACKGROUND_OPA, 0);
    weatherDateGroup_->Add(weatherBackground_);

    for (int i = 0; i < LABEL_COUNT; i++) {
        gLabel[i] = CreateLabel((const char *)text[i], labelRect[i], fonstSize[i]);
        weatherDateGroup_->Add(gLabel[i]);
    }
    dateLabel_ = gLabel[DATE_LABEL_ID];
    timeLabel_ = gLabel[TIME_LABEL_ID];
    weekLabel_ = gLabel[WEEK_LABEL_ID];
    tempLabel_ = gLabel[TEMP_LABEL_ID];
    weatherLabel_ = gLabel[WEATH_LABEL_ID];

    UpdateTime(false);
}

static UIViewGroup *GetItem(UI_RECT rect, const char *image, UI_RECT imgRect, const char *text,
                            UI_RECT txtRect, UIView::OnClickListener *click, UILabel **label)
{
    char iconPath[256] = {0};
    const char *pathHead = GetSrcPath();
    printf("[%s|%d]\n", __func__, __LINE__);
    UIViewGroup *group = new UIViewGroup();
    group->SetPosition(rect.x, rect.y, rect.w, rect.h);
    group->SetStyle(STYLE_BACKGROUND_OPA, 0);
    group->SetStyle(STYLE_BORDER_RADIUS, GROUP_VIEW_RADIUS);
    group->SetStyle(STYLE_BACKGROUND_COLOR, Color::ColorTo32(Color::Gray()));

    (void)sprintf_s(iconPath, sizeof(iconPath), "%s/%s", pathHead, SMALL_ITEM_BKG);
    UIImageView *backImage = new UIImageView();
    backImage->SetPosition(0, 0, rect.w, rect.h);
    backImage->SetSrc((char *)iconPath);
    backImage->SetStyle(STYLE_BACKGROUND_OPA, 0);
    group->Add(backImage);

    memset(iconPath, 0x00, sizeof(iconPath));
    (void)sprintf_s(iconPath, sizeof(iconPath), "%s/%s", pathHead, image);
    UIImageView *icon = new UIImageView();
    icon->SetPosition(imgRect.x, imgRect.y, imgRect.w, imgRect.h);
    icon->SetSrc((char *)iconPath);
    icon->SetStyle(STYLE_BACKGROUND_OPA, 0);
    icon->SetTouchable(true);
    icon->SetOnClickListener(click);
    group->Add(icon);

    UILabel *msgLabel = CreateLabel(text, txtRect, FONT_SIZE_28);
    group->Add(msgLabel);
    *label = msgLabel;

    group->SetTouchable(true);
    group->SetOnClickListener(click);
    group->Invalidate();

    return group;
}

void HoodsAbilitySlice::SetListItem()
{
    const int itemRows = 2;
    const char *iconPath[ITEM_COUNT] = {
        ICON_VIDEO_PATH,
        iconimage_PATH,
        ICON_CAMERA_PATH,
        ICON_CAMERA_PATH
    };

    const char *text[ITEM_COUNT] = {
        "视频",
        "图片",
        "实时监控1",
        "实时监控2"
    };

    const char *sliceName[ITEM_COUNT] = {
        "FileListAbilitySlice",
        "FileListAbilitySlice",
        "CameraAbilitySlice",
        "No effect"
    };
    printf("[%s|%d]\n", __func__, __LINE__);
    itemGroup_ = new UIViewGroup();
    itemGroup_->SetPosition(ITEM_GROUP_X, ITEM_GROUP_Y, ITEM_GROUP_W, ITEM_GROUP_H);
    itemGroup_->SetStyle(STYLE_BACKGROUND_OPA, 0);

    for (int i = 0; i < ITEM_COUNT; i++) {
        int x = (i % itemRows) * (ITEM_X_POS + ITEM_WIDTH);
        int y = (i / itemRows) * (ITEM_Y_POS + ITEM_HIEGHT);

        UI_RECT groupR = {0, 0, ITEM_WIDTH, ITEM_HIEGHT};
        UI_RECT imageR = {ITEM_ICON_X, ITEM_ICON_Y, ITEM_ICON_W, ITEM_ICON_H};
        UI_RECT textR = {ITEM_LABEL_X, ITEM_LABEL_Y, ITEM_LABEL_W, ITEM_LABEL_H};

        groupR.x = x;
        groupR.y = y;

        HoodsButtonClickListener *itemClick = new HoodsButtonClickListener(this);
        if (i <= IMAGE_ITEM) {
            itemClick->SetSliceInfo(sliceName[i], i == VIDEO_ITEM ? (const char *)"video" : (const char *)"image");
        } else {
            itemClick->SetSliceInfo(sliceName[i], nullptr);
        }
        UIViewGroup *view = GetItem(groupR, iconPath[i], imageR, text[i], textR, itemClick, &listLabel_[i]);
        itemGroup_->Add(view);
    }

    UpdateVideoImage(VIDEO_ITEM);
    UpdateVideoImage(IMAGE_ITEM);
}

static bool IsFileType(const char *name, int type)
{
    const int fileTypes = 2;

    const char *g_type[fileTypes] = {
        ".mp4",
        ".jpg"
    };

    if (type >= fileTypes) {
        return false;
    }

    char *ptr = (char *)strrchr(name, '.');
    if (ptr == nullptr) {
        return false;
    }

    return (strcasecmp(g_type[type], ptr) == 0);
}

static int SearchList(const char *dirPath, int type)
{
    int count = 0;
    DIR *dir;
    struct dirent *entry;

    dir = opendir(dirPath);
    if (dir == nullptr) {
        return count;
    }

    while ((entry = readdir(dir)) != nullptr) {
        if (IsFileType(entry->d_name, type)) {
            count++;
        }
    }

    closedir(dir);
    dir = nullptr;

    return count;
}

int HoodsAbilitySlice::DialogDisplay(const char *msg, int type, int timeout)
{
    int result = 0;
    int timeCnt = 0;

    if (dialog_ == nullptr) {
        return -1;
    }

    dialog_->Display(msg, type, timeout);
    if (type != DIALOG_SELECT) {
        return 0;
    }

    while (true) {
        result = dialog_->GetResult();
        if (result != -1) {
            break;
        }

        sleep(1);
        if (timeout > 0 && ++timeCnt >= timeout) {
            result = 0;
            break;
        }
    }

    return result;
}

static int ShowDialog(void *data, const char *msg, DIALOG_TYPE type, int timeout)
{
    HoodsAbilitySlice *hoods = (HoodsAbilitySlice *)data;
    if (hoods == nullptr) {
        return -1;
    }

    return hoods->DialogDisplay(msg, type, timeout);
}

static bool isVideo(const char *name)
{
    const char *suffix = ".mp4";
    char *ptr = (char *)strrchr(name, '.');

    if (ptr == nullptr) {
        return false;
    }

    return (strncmp(ptr, suffix, strlen(suffix)) == 0) ? true : false;
}

bool HoodsAbilitySlice::FileIsUpdate()
{
#if 1
    if (FileServerIsUpdate() == 1) {
        int lv = g_videoNumber_;
        int lp = g_pictrueNumber_;

        while (1) {
            char name[256] = {0};
            if (FileServerPopupFile(name, sizeof(name)) != 0) {
                break;
            }
            if (isVideo(name)) {
                g_videoNumber_++;
            } else {
                g_pictrueNumber_++;
            }
        }

        if (lv != g_videoNumber_) {
            UpdateVideoImage(VIDEO_ITEM);
        }

        if (lp != g_pictrueNumber_) {
            UpdateVideoImage(IMAGE_ITEM);
        }

        return true;
    }
#endif
    return false;
}

void HoodsAbilitySlice::Callback()
{
    if (g_isActivity_) {
        UpdateTime(1);
        if (FileIsUpdate()) {
            g_timeCount_ = 0;
            return;
        }

        if (++g_timeCount_ >= TASK_TIME_OUT) {
            AbilitySlice *nextSlice;
            Want wantData = { nullptr };

            nextSlice = AbilityLoader::GetInstance().GetAbilitySliceByName("ScreenSaverAbilitySlice");
            if (nextSlice == nullptr) {
                printf("undefined nextSlice --->ScreenSaverAbilitySlice! \n");
                return;
            }
            Present(*nextSlice, wantData);
        }
    }
}

void HoodsAbilitySlice::OnStart(const Want &want)
{
    AbilitySlice::OnStart(want);
    printf("[%s|%d] HoodsAbilitySlice OnStart \n", __func__, __LINE__);
    FileServerInit(ShowDialog, (void *)this);
    rootView_ = RootView::GetWindowRootView();
    rootView_->SetPosition(START_XPOS, START_YPOS, SCREEN_WIDTH, SCREEN_HEIGHT);
    rootView_->SetStyle(STYLE_BACKGROUND_OPA, 0);

    backClickImage_ = new UIImageView();
    backClickImage_->SetPosition(START_XPOS, START_YPOS, CLICK_BACK_ICON_W, CLICK_BACK_ICON_H);
    backClickImage_->SetStyle(STYLE_BACKGROUND_OPA, 0);
    backClickImage_->SetTouchable(true);

    char iconPath[256] = {0};
    const char *pathHead = GetSrcPath();
    (void)sprintf_s(iconPath, sizeof(iconPath), "%s/%s", pathHead, ICON_BACK1_PATH);
    backButton_ = new UIImageView();
    backButton_->SetPosition(BACK_ICON_X, BACK_ICON_Y, BACK_ICON_W, BACK_ICON_H);
    backButton_->SetSrc((char *)iconPath);
    backButton_->SetStyle(STYLE_BACKGROUND_OPA, 0);
    backButton_->SetTouchable(true);
    backClickListener_ = new HoodsButtonClickListener(this);
    backClickImage_->SetOnClickListener(backClickListener_);
    backButton_->SetOnClickListener(backClickListener_);

    memset(iconPath, 0x00, sizeof(iconPath));
    (void)sprintf_s(iconPath, sizeof(iconPath), "%s/%s", pathHead, HOODS_BACKGROUND);
    background_ = new UIImageView();
    background_->SetPosition(START_XPOS, START_YPOS, CLICK_BACK_ICON_W, CLICK_BACK_ICON_H);
    background_->SetSrc((char *)iconPath);
    background_->SetStyle(STYLE_BACKGROUND_OPA, 0);

    g_videoNumber_ = SearchList(VIDEO_DEFAULT_PATH, VIDEO_ITEM);
    g_videoNumber_ += SearchList(RECV_FILE_PATH, VIDEO_ITEM);

    g_pictrueNumber_ = SearchList(IMAGE_DEFAULT_PATH, IMAGE_ITEM);
    g_pictrueNumber_ += SearchList(RECV_FILE_PATH, IMAGE_ITEM);

    SetTimeWeatherView();
    SetListItem();

    rootView_->Add(background_);
    rootView_->Add(backClickImage_);
    rootView_->Add(backButton_);

    rootView_->Add(weatherDateGroup_);
    rootView_->Add(itemGroup_);

    dialog_ = new PopupDialog();
    dialog_->Create(rootView_, POP_WIN_X, POP_WIN_Y, POP_WIN_W, POP_WIN_H);
    SetUIContent(rootView_);
    rootView_->Invalidate();
    TaskExecute();
}

void HoodsAbilitySlice::OnInactive()
{
    AbilitySlice::OnInactive();
    printf("[%s|%d] HoodsAbilitySlice OnInactive\n", __func__, __LINE__);
}

void HoodsAbilitySlice::OnActive(const Want &want)
{
    AbilitySlice::OnActive(want);
    printf("[%s|%d] HoodsAbilitySlice OnActive \n", __func__, __LINE__);
    g_timeCount_ = 0;
    g_isActivity_ = true;

    FileServerSetDialog(ShowDialog, (void *)this);
}

void HoodsAbilitySlice::OnBackground()
{
    AbilitySlice::OnBackground();
    printf("[%s|%d] HoodsAbilitySlice OnBackground\n", __func__, __LINE__);
    g_isActivity_ = false;
}

void HoodsAbilitySlice::OnStop()
{
    AbilitySlice::OnStop();
    printf("[%s|%d] HoodsAbilitySlice OnStop \n", __func__, __LINE__);
}

}
